package model

import (
	"OJCenter/global"
	"OJCenter/idl"
	"github.com/mitchellh/mapstructure"
)

func (m *Model) CreateContest(Contest *idl.Contest) error {
	err := m.C.InsertContestInfo(Contest)
	if err != nil {
		return err
	}
	return nil
}

func (m *Model) DeleteContestByCID(cids []int64) (int, *[]int64) {
	sum := len(cids)
	var fu []int64
	for _, cid := range cids {
		err := m.C.DeleteContestInfo(&idl.Contest{Cid: cid})
		if err != nil {
			sum--
			fu = append(fu, cid)
			global.Logger.Errorf("uid:%v,delete Contest info failed,err:%v", cid, err)
		}
	}
	return sum, &fu
}

func (m *Model) GetContestList(page, limit int) (*[]idl.Contest, error) {
	return m.C.GetContestList(page, limit)
}

func (m *Model) SelectContest(con idl.Contest) (*[]idl.Contest, error) {
	return m.C.SelectContest(&con)
}

func (m *Model) UpdateContest(Contests *[]idl.Contest) (int, *[]idl.Contest) {
	sum := len(*Contests)
	var fu []idl.Contest
	for _, contest := range *Contests {
		var info map[string]interface{}
		err := mapstructure.Decode(&contest, &info)
		if err != nil {
			fu = append(fu, contest)
			global.Logger.Error("update marshal failed")
			sum--
			continue
		}
		err = m.C.UpdateContestInfo(info)
		if err != nil {
			sum--
			fu = append(fu, contest)
			global.Logger.Errorf("id:%v,update Contest info failed,err:%v", contest.Cid, err)
		}
	}
	return sum, &fu
}

func (m *Model) SelectContestDetails(con idl.ContestDetailInfo) (*[]idl.ContestDetailInfo, error) {
	return m.Cd.SelectContestDetail(&con)
}

func (m *Model) GetContestInfoByCID(cid int64) (*[]idl.Problem, error) {
	pids, err := m.Cd.GetContestDetailPidsFromCache(cid)
	if err != nil {
		data, err := m.Cd.GetContestDetailInfosFromData(cid)
		if err != nil {
			return nil, err
		}
		ret := make([]idl.Problem, len(*data))
		for i, detail := range *data {
			pro, err := m.P.GetProblemInfo(detail.Pid)
			if err != nil {
				global.Logger.Errorf("problem:%d info get failed,err:%v", detail.Pid, err)
				continue
			}
			ret[i] = *pro
		}
		return &ret, nil
	}
	ret := make([]idl.Problem, len(*pids))
	for i, pid := range *pids {
		pro, err := m.P.GetProblemInfo(pid)
		if err != nil {
			global.Logger.Errorf("problem:%d info get failed,err:%v", pid, err)
			continue
		}
		ret[i] = *pro
	}
	return &ret, nil
}

func (m *Model) UpdateContestDetails(ContestDetails *[]idl.ContestDetailInfo) (int, *[]idl.ContestDetailInfo) {
	sum := len(*ContestDetails)
	var fu []idl.ContestDetailInfo
	for _, ContestDetail := range *ContestDetails {
		var info map[string]interface{}
		err := mapstructure.Decode(&ContestDetail, &info)
		if err != nil {
			fu = append(fu, ContestDetail)
			global.Logger.Error("update marshal failed")
			sum--
			continue
		}
		err = m.Cd.UpdateContestDetailInfo(info)
		if err != nil {
			sum--
			fu = append(fu, ContestDetail)
			global.Logger.Errorf("info:%v,delete ContestDetail info failed,err:%v", ContestDetail, err)
		}
	}
	return sum, &fu
}

func (m *Model) CreateContestDetail(details *[]idl.ContestDetailInfo) (*[]idl.ContestDetailInfo, error) {
	var fails []idl.ContestDetailInfo
	var err error
	for _, detail := range *details {
		err = m.Cd.InsertContestDetailInfo(&detail)
		if err != nil {
			fails = append(fails, detail)
			global.Logger.Errorf("problem:%d insert contest:%d failed,err:%v", detail.Pid, detail.Cid, err)
		}

	}
	return &fails, err
}

func (m *Model) DelContestDetail(details *[]idl.ContestDetailInfo) (*[]idl.ContestDetailInfo, error) {
	var fails []idl.ContestDetailInfo
	var err error
	for _, detail := range *details {
		err = m.Cd.DeleteContestDetailInfo(&detail)
		if err != nil {
			fails = append(fails, detail)
			global.Logger.Errorf("problem:%d insert contest:%d failed,err:%v", detail.Pid, detail.Cid, err)
		}

	}
	return &fails, err
}

func (m *Model) IsContestDetailInfoHasP(cid int64, pid int64) (bool, error) {
	return m.Cd.IsContestDetailInfoHasP(cid, pid)
}
